﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Data;

namespace Fis.Win.Rules
{
    public class SynchronizeViewProvider : ClientViewProvider
    {
        public SynchronizeViewProvider()
        {
            syncTimer = new System.Timers.Timer();
            syncTimer.Enabled = false;
            syncTimer.Interval = 60000;
            syncTimer.Elapsed += new System.Timers.ElapsedEventHandler(syncTimer_Elapsed);
        }

        public double SyncInterval { set { syncTimer.Interval = value; } }
        public string PingUri { get; set; }

        public void Start() { syncTimer.Start(); }
        public void Stop()
        {
            if (syncTimer.Enabled)
                syncTimer.Stop();
        }

        void syncTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
           if (syncLock)
                return;



            ///未连接网络
            if (!NetStateClient())
                return;


            syncLock = true;

            try
            {
                ExecuteUpdate(null);
            }
            catch
            {

            }

            syncLock = false;
        }

        System.Timers.Timer syncTimer = new System.Timers.Timer();
        bool syncLock = false;


        public bool NetStateClient()
        {
            System.Net.WebClient client = new System.Net.WebClient();
            bool result = false;
            try
            {
                using (var stream = client.OpenRead(Fis.Win.Utils.AppConfig.ServiceState))
                {
                    var request = new System.IO.StreamReader(stream).ReadToEnd();
                    result = !string.IsNullOrEmpty(request);
                }
            }
            catch
            {
                client.Dispose();
            }
            Fis.Win.Utils.AppSession.IsNetConnect = result;
            return result;
        }

        public bool NetStatePing()
        {
            System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
            Uri u = new Uri(ServiceProcess.Proxy.Uri);
            bool test = false;
            try
            {
                test = p.Send(u.Host).Status == System.Net.NetworkInformation.IPStatus.Success;
            }
            catch
            {

            }

            ///链接状态
            Fis.Win.Utils.AppSession.IsNetConnect = test;
            return test;
        }

        public override bool ExecuteUpdateXtra(Hashtable viewModel)
        {
            var range = int.Parse(Fis.Win.Utils.AppSession.Range);
            range = (range > 12) ? 12 : (range < 1) ? 1 : range;
            var param = new Hashtable();
            //本期第一天
            param["SyncDate"] = DateTime.Parse(
                string.Format("{0}-{1}-1 0:00:00", Fis.Win.Utils.AppSession.Year, range));

            syncTimer.Stop();
            syncLock = true;
            var exec = ExecuteUpdate(param);
            syncLock = false;
            syncTimer.Start();
            Message = ServiceProcess.Message;
            return exec;
        }

        public override bool ExecuteUpdate(System.Collections.Hashtable viewModel)
        {
            var xml = Agile.Engine.ObjectContext.GetResource("SqlResource");
            DateTime lastSync = DateTime.MinValue;
            var param = Fis.Win.Utils.AppSession.CreateServiceParamter(viewModel ?? new System.Collections.Hashtable());
            if (!param.ContainsKey("SyncDate"))
            {
                lastSync = DataContext.DefaultModel.ExecuteScalar(DateTime.Now, xml.GetString("sync_select"));
                param["SyncDate"] = lastSync;
            }
            var exec = InvokeService(param);

            if (exec)
            {
                lastSync = (DateTime)ServiceProcess.Result["SyncDate"];
                DataContext.DefaultModel.ExecuteNonQuery(xml.Format("sync_update", lastSync));

                if (ServiceProcess.Result.ContainsKey("data"))
                {
                    var sync = Agile.Engine.Utils.StringUtils.FromJson<Hashtable>(ServiceProcess.Result["data"].ToString());

                    foreach (DictionaryEntry entry in sync)
                    {
                        var key = entry.Key.ToString().ToUpper();
                        ///同步
                        switch (key)
                        {
                            ///新版本
                            case "NEWVERSION":
                                var source = Agile.Engine.Utils.ZipUtils.UnZipBase64(entry.Value.ToString());
                                var target = System.IO.Path.Combine(Agile.Engine.ObjectContext.Environment.Update, "update.xap");
                                Agile.Engine.Utils.IOUtils.CreateDirectory(target);

                                using (var f = System.IO.File.OpenWrite(target))
                                {
                                    var ms = new System.IO.MemoryStream(source);
                                    ms.CopyTo(f);
                                }

                                break;
                            ///删除信息
                            case "DELETEINFO":
                                var delete = Agile.Engine.Utils.ZipUtils.UnZipDataTable(entry.Value.ToString());
                                delete.TableName = key;
                                SynchronizeDelete(delete);
                                break;
                            ///反结帐
                            case "RESET":
                                var reset = Agile.Engine.Utils.ZipUtils.UnZipDataTable(entry.Value.ToString());
                                reset.TableName = key;
                                SynchronizeReset(reset);
                                break;
                            case "IMPORT":
                                var import = Agile.Engine.Utils.ZipUtils.UnZipDataTable(entry.Value.ToString());
                                import.TableName = key;
                                SynchronizeImport(import);

                                break;
                            ///默认同步
                            default:
                                var data = Agile.Engine.Utils.ZipUtils.UnZipDataTable(entry.Value.ToString());
                                data.TableName = key;
                                Synchronize(data);

                                if (Fis.Win.Utils.CacheContext.CacheKeys.Contains(key))
                                {
                                    Fis.Win.Utils.CacheContext.RefreshCache(key.ToUpper());
                                }
                                break;
                        }

                    }

                }

            }

            return exec;
        }

        public void SynchronizeReset(DataTable data)
        {
            //FXTRA1 UNREST
            //FXTRA2 range  对应期间,反初始化为0，反结帐为对应期间

            DataContext.DefaultModel.ExecuteTransaction(
                () =>
                {
                    for (var i = 0; i < data.Rows.Count; i++)
                    {
                        DataContext.DefaultModel.Delete("TREST",
                            string.Format("FRANGE={0}", data.Rows[i]["FXTRA2"]));
                    }
                });

        }

        /// <summary>
        /// 同步删除数据
        /// </summary>
        /// <param name="data"></param>
        public void SynchronizeDelete(DataTable data)
        {
            //FXTRA1 table
            //FXTRA2 sid

            DataContext.DefaultModel.ExecuteTransaction(
                () =>
                {
                    for (var i = 0; i < data.Rows.Count; i++)
                    {
                        {
                            DataContext.DefaultModel.Delete(data.Rows[i]["FXTRA1"].ToString(),
                                string.Format("SID='{0}'", data.Rows[i]["FXTRA2"]));
                        }
                    }
                });

        }

        void SynchronizeImport(DataTable data)
        {
            Stop();
            Hashtable model = Fis.Win.Utils.AppSession.CreateServiceParamter(new Hashtable());
            foreach (var d in data.AsEnumerable())
            {
                var key = d["FXTRA1"].ToString();
                switch (key.ToUpper())
                {
                    //凭证主表
                    case "TBILLMASTER":
                        break;
                    //基础数据
                    default:
                        //下载所有信息
                        model["ONETABLEALL"] = key;
                        var exec = InvokeService(model);
                        if (exec)
                        {
                            var syncData = Agile.Engine.Utils.ZipUtils.UnZipDataTable(ServiceProcess.Result["data"].ToString());
                            DataContext.DefaultModel.ExecuteTransaction(
                                () =>
                                {
                                    DataContext.DefaultModel.Delete(key, "1=1");
                                    new Agile.Engine.Data.DataAccess() { Context = DataContext, TableName = key }.AddNew(syncData.Select());
                                }
                                );
                        }
                        //清空本地表
                        //写入同步
                        break;
                }

            }
            Start();
        }

        /// <summary>
        /// 同步更新数据
        /// </summary>
        /// <param name="data"></param>
        public void Synchronize(System.Data.DataTable data)
        {
            var current = DataContext.DefaultModel.QueryTable(data.TableName);
            current.PrimaryKey = new DataColumn[] { current.Columns["SID"] };

            List<DataRow> list = new List<DataRow>();
            foreach (var d in data.AsEnumerable())
            {
                var sid = d["SID"].ToString();
                var find = current.Rows.Find(sid);
                if (find != null)
                    list.Add(find);
            }

            DataContext.DefaultModel.ExecuteTransaction(
                () =>
                {
                    if (list.Count > 0)
                        DataContext.DefaultModel.Delete(data.TableName, list.ToArray());
                    DataContext.DefaultModel.UpdateTable(data);
                });
        }
    }
}
